function varargout = annotation_gui(varargin)
% ANNOTATION_GUI MATLAB code for annotation_gui.fig
%      ANNOTATION_GUI, by itself, creates a new ANNOTATION_GUI or raises the existing
%      singleton*.
%
%      H = ANNOTATION_GUI returns the handle to a new ANNOTATION_GUI or the handle to
%      the existing singleton*.
%
%      ANNOTATION_GUI('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in ANNOTATION_GUI.M with the given input arguments.
%
%      ANNOTATION_GUI('Property','Value',...) creates a new ANNOTATION_GUI or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before annotation_gui_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to annotation_gui_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help annotation_gui

% Last Modified by GUIDE v2.5 31-Oct-2012 20:12:10

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @annotation_gui_OpeningFcn, ...
                   'gui_OutputFcn',  @annotation_gui_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT

% --- Executes just before annotation_gui is made visible.
function annotation_gui_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to annotation_gui (see VARARGIN)

% Choose default command line output for annotation_gui
handles.output = hObject;

handles.pre_built_binary_path = getappdata(0,'pre_built_binary_path');
handles.input_folder = getappdata(0,'input_folder');
load(handles.pre_built_binary_path);
handles.guesses = guesses;
handles.num_of_files = length(guesses);
handles.currentindex = 1;

% Read the picture
impath = fullfile(handles.guesses{handles.currentindex}.filepath);

% Load the guess binary
I = imread(impath);

% Read the guess
guess_data = handles.guesses{handles.currentindex}.data;
xc_iris = guess_data(1,1);
yc_iris = guess_data(1,2);

radius_iris = guess_data(1,3);
[px, py] = circlepoints(radius_iris);

upper_eyelid = guess_data(2:6,1:2);
lower_eyelid = guess_data(7:end,1:2);

handles.upper_data = upper_eyelid;
handles.lower_data = lower_eyelid;
handles.iris_data = guess_data(1,:);

upper_range = upper_eyelid(1,1):.1:upper_eyelid(5,1);
upper_yy = spline(upper_eyelid(:,1),upper_eyelid(:,2),upper_range);

lower_range = lower_eyelid(1,1):.1:lower_eyelid(5,1);
lower_yy = spline(lower_eyelid(:,1),lower_eyelid(:,2),lower_range);

px = px + xc_iris;
py = py + yc_iris;

% Draw the picture
imshow(I);

% Draw the guesses
hold on;
handles.iris = plot(px,py,'LineWidth',5);
handles.upper1 = plot(upper_range,upper_yy,'LineWidth',5);
handles.lower1 = plot(lower_range,lower_yy,'LineWidth',5);

set(handles.backbutton,'Enable','off');

% Update handles structure
guidata(hObject, handles);

% --- Outputs from this function are returned to the command line.
function varargout = annotation_gui_OutputFcn(hObject, eventdata, handles)
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
varargout{1} = handles.output;

% --- Executes on button press in nextbutton.
function nextbutton_Callback(hObject, eventdata, handles)
% Call back for the Next button
% Save the annotation
annotations = zeros(11,3);
annotations(1,:) = handles.iris_data;
annotations(2:6,1:2) = handles.upper_data;
annotations(7:end,1:2) = handles.lower_data;

guess.filepath = handles.guesses{handles.currentindex}.filepath;
guess.data = annotations;
handles.guesses{handles.currentindex} = guess;
guesses = handles.guesses;

save(handles.input_folder,'guesses');
disp('Saved.');

if handles.currentindex < handles.num_of_files
    % Display the next picture
    set(handles.backbutton,'Enable','on');
    handles.currentindex = handles.currentindex + 1;
    impath = fullfile(handles.guesses{handles.currentindex}.filepath);
    I = imread(impath);

    % Update the status text
    set(handles.status_text,'String',sprintf('%d out of %d done',handles.currentindex,handles.num_of_files))
else
    % Disable to approve button
    set(handles.nextbutton,'Enable','off');
    
    % Set the status text
    set(handles.status_text,'String',sprintf('%d out of %d done',handles.currentindex,handles.num_of_files))
end

guess_data = handles.guesses{handles.currentindex}.data;
xc_iris = guess_data(1,1);
yc_iris = guess_data(1,2);

radius_iris = guess_data(1,3);
[px, py] = circlepoints(radius_iris);

upper_eyelid = guess_data(2:6,1:2);
lower_eyelid = guess_data(7:end,1:2);

handles.upper_data = upper_eyelid;
handles.lower_data = lower_eyelid;
handles.iris_data = guess_data(1,:);

upper_range = upper_eyelid(1,1):.1:upper_eyelid(5,1);
upper_yy = spline(upper_eyelid(:,1),upper_eyelid(:,2),upper_range);

lower_range = lower_eyelid(1,1):.1:lower_eyelid(5,1);
lower_yy = spline(lower_eyelid(:,1),lower_eyelid(:,2),lower_range);

px = px + xc_iris;
py = py + yc_iris;

% Draw the picture
hold off;
imshow(I); axis auto;

% Draw the guesses
hold on;
handles.iris = plot(px,py,'LineWidth',5);
handles.upper1 = plot(upper_range,upper_yy,'LineWidth',5);
handles.lower1 = plot(lower_range,lower_yy,'LineWidth',5);

% Update handles structure
guidata(hObject, handles);


% --------------------------------------------------------------------
function FileMenu_Callback(hObject, eventdata, handles)
% hObject    handle to FileMenu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


% --------------------------------------------------------------------
function OpenMenuItem_Callback(hObject, eventdata, handles)
% hObject    handle to OpenMenuItem (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
file = uigetfile('*.fig');
if ~isequal(file, 0)
    open(file);
end

% --------------------------------------------------------------------
function PrintMenuItem_Callback(hObject, eventdata, handles)
% hObject    handle to PrintMenuItem (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
printdlg(handles.figure1)

% --------------------------------------------------------------------
function CloseMenuItem_Callback(hObject, eventdata, handles)
% hObject    handle to CloseMenuItem (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
selection = questdlg(['Close ' get(handles.figure1,'Name') '?'],...
                     ['Close ' get(handles.figure1,'Name') '...'],...
                     'Yes','No','Yes');
if strcmp(selection,'No')
    return;
end

delete(handles.figure1)


% --- Executes on selection change in popupmenu1.
function popupmenu1_Callback(hObject, eventdata, handles)
% hObject    handle to popupmenu1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

set(hObject,'Enable','off');
set(handles.nextbutton,'Enable','off');
set(handles.backbutton,'Enable','off');
set(handles.mainpanelbutton,'Enable','off');
set(handles.donebutton,'Enable','on');

contents = get(hObject,'String');
selection = contents{get(hObject,'Value')};
delete(handles.iris)

% Disable the drop down
handles.upper_control = cell(1,size(handles.upper_data,1));
handles.lower_control = cell(1,size(handles.lower_data,1));
if strcmp(selection,'upperlid')
    delete(handles.lower1)
    for i=1:size(handles.upper_data,1)
        point_handle = impoint(gca,handles.upper_data(i,:));
        setString(point_handle,i);
        setColor(point_handle,'r');
        handles.upper_control{i} = point_handle;
        addNewPositionCallback(point_handle,@(pos) redraw(pos,i,true));
    end
elseif strcmp(selection,'lowerlid')
    delete(handles.upper1)
    for i=1:size(handles.lower_data,1)
        point_handle = impoint(gca,handles.lower_data(i,:));
        setString(point_handle,i);
        setColor(point_handle,'r');
        handles.lower_control{i} = point_handle;
        addNewPositionCallback(point_handle,@(pos) redraw(pos,i,false));
    end
elseif strcmp(selection,'iris')
    radius = handles.iris_data(3);
    minx = handles.iris_data(1) - handles.iris_data(3);
    miny = handles.iris_data(2) - handles.iris_data(3);
    width = 2*radius;
    bb = [minx miny width width];
    h = imellipse(gca,bb);
    h.setFixedAspectRatioMode(true);
    handles.iris_handle = h;
end
guidata(hObject, handles);


% --- Executes during object creation, after setting all properties.
function popupmenu1_CreateFcn(hObject, eventdata, handles)
% hObject    handle to popupmenu1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: popupmenu controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
     set(hObject,'BackgroundColor','white');
end

set(hObject, 'String', {'choose one to edit...','upperlid','lowerlid','iris'});


% --- Executes during object creation, after setting all properties.
function axes1_CreateFcn(hObject, eventdata, handles)


% --- Executes on key press with focus on nextbutton and none of its controls.
function nextbutton_KeyPressFcn(hObject, eventdata, handles)

% --- Executes on button press in donebutton.
function donebutton_Callback(hObject, eventdata, handles)

% Delete the control points
try
    for i=1:length(handles.upper_control)
        delete(handles.upper_control{i});
    end
    delete(handles.upper1);
catch exception
    exception
end

try
    for i=1:length(handles.lower_control)
        delete(handles.lower_control{i});
    end
    
    delete(handles.lower1);
catch exception
    exception
end

try
    iris_handle = handles.iris_handle;
    iris_position = iris_handle.getPosition();
    radius = floor(iris_position(3)/2);
    xc = iris_position(1) + floor(iris_position(3)/2);
    yc = iris_position(2) + floor(iris_position(3)/2);
    handles.iris_data = [xc yc radius];
    delete(handles.iris_handle);
catch exception
    exception
end

% Redraw the image
iris_data = handles.iris_data;
upper_eyelid = handles.upper_data;
lower_eyelid = handles.lower_data;

xc_iris = iris_data(1);
yc_iris = iris_data(2);
radius_iris = iris_data(3);
[px, py] = circlepoints(radius_iris);

[maxr,maxc] = size(upper_eyelid);

upper_range = upper_eyelid(1,1):.1:upper_eyelid(maxr,1);
upper_yy = spline(upper_eyelid(:,1),upper_eyelid(:,2),upper_range);

lower_range = lower_eyelid(1,1):.1:lower_eyelid(maxr,1);
lower_yy = spline(lower_eyelid(:,1),lower_eyelid(:,2),lower_range);

px = px + xc_iris;
py = py + yc_iris;

% Draw the guesses
handles.iris = plot(px,py,'LineWidth',5);
handles.upper1 = plot(upper_range,upper_yy,'LineWidth',5);
handles.lower1 = plot(lower_range,lower_yy,'LineWidth',5);

% Enable the approve button
set(handles.popupmenu1,'Enable','on');
if handles.currentindex < handles.num_of_files
    set(handles.nextbutton,'Enable','on');
end

if handles.currentindex > 1
    set(handles.backbutton,'Enable','on');
end
set(handles.mainpanelbutton,'Enable','on');
set(handles.donebutton,'Enable','off');
set(handles.popupmenu1,'Value',1);

guidata(hObject, handles);

% --- Executes on key press with focus on donebutton and none of its controls.
function donebutton_KeyPressFcn(hObject, eventdata, handles)

function redraw(pos,i,upper)
% Delete the existing plot

handles = guidata(gcf);
if upper
    delete(handles.upper1);
    data = handles.upper_data;
    data(i,:) = pos;
    data_range = data(1,1):.1:data(5,1);
    yy = spline(data(:,1),data(:,2),data_range);
    handles.upper1 = plot(data_range,yy,'LineWidth',5);
    uistack(handles.upper1,'down',5)
    handles.upper_data = data;
else
    delete(handles.lower1);
    data = handles.lower_data;
    data(i,:) = pos;
    data_range = data(1,1):.1:data(5,1);
    yy = spline(data(:,1),data(:,2),data_range);
    plot_handle = plot(data_range,yy,'LineWidth',5);
    handles.lower1 = plot_handle;
    uistack(handles.lower1,'down',6)
    handles.lower_data = data;
end

guidata(gcf,handles);


% --- Executes on button press in backbutton.
function backbutton_Callback(hObject, eventdata, handles)
annotations = zeros(11,3);
annotations(1,:) = handles.iris_data;
annotations(2:6,1:2) = handles.upper_data;
annotations(7:end,1:2) = handles.lower_data;

guess.filepath = handles.guesses{handles.currentindex}.filepath;
guess.data = annotations;
handles.guesses{handles.currentindex} = guess;
guesses = handles.guesses;

save(handles.input_folder,'guesses');
disp('Saved.');

if handles.currentindex > 1
    % Display the next picture
    handles.currentindex = handles.currentindex - 1;
    impath = fullfile(handles.guesses{handles.currentindex}.filepath);
    I = imread(impath);

    % Update the status text
    set(handles.status_text,'String',sprintf('%d out of %d done',handles.currentindex,handles.num_of_files))
    
    if handles.currentindex == 1
        set(handles.backbutton,'Enable','off');
    end
end

guess_data = handles.guesses{handles.currentindex}.data;
xc_iris = guess_data(1,1);
yc_iris = guess_data(1,2);

radius_iris = guess_data(1,3);
[px, py] = circlepoints(radius_iris);

upper_eyelid = guess_data(2:6,1:2); lower_eyelid = guess_data(7:end,1:2);

handles.upper_data = upper_eyelid; handles.lower_data = lower_eyelid;
handles.iris_data = guess_data(1,:);

upper_range = upper_eyelid(1,1):.1:upper_eyelid(5,1);
upper_yy = spline(upper_eyelid(:,1),upper_eyelid(:,2),upper_range);

lower_range = lower_eyelid(1,1):.1:lower_eyelid(5,1);
lower_yy = spline(lower_eyelid(:,1),lower_eyelid(:,2),lower_range);

px = px + xc_iris; py = py + yc_iris;

% Draw the picture
hold off; imshow(I); axis auto;

% Draw the guesses
hold on; handles.iris = plot(px,py,'LineWidth',5);
handles.upper1 = plot(upper_range,upper_yy,'LineWidth',5);
handles.lower1 = plot(lower_range,lower_yy,'LineWidth',5);

% Update handles structure
guidata(hObject, handles);

% --- Executes on button press in mainpanelbutton.
function mainpanelbutton_Callback(hObject, eventdata, handles)
outerui;
close(handles.output);


% --- Executes on button press in pushbutton8.
function pushbutton8_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton8 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
